package com.hevery.security.core.authentication.mobile;

import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author: zhy
 * @description: 短信验证码登录验证过滤器
 * @date: created on 2017/11/4
 * @modified by:
 */
public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public static final String HEVERY_FROM_MOBILE_KEY = "mobile";

    /**在请求中表示手机号的参数*/
    private String mobileParameter = HEVERY_FROM_MOBILE_KEY;

    /**当前的过滤器只处理POST请求*/
    private boolean postOnly = true;

    /**
     * 表示当前过滤器处理的请求是什么，即在标准登录页中短信验证码的表单提交的请求
     */
    public SmsCodeAuthenticationFilter(){
        super(new AntPathRequestMatcher("/authentication/mobile", "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        //判断当前的请求是否是post请求，如果不是就抛出异常
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException(
                    "Authentication method not supported: " + request.getMethod());
        }

        //获取请求中的手机号
        String mobile = obtainUsername(request);

        if (mobile == null) {
            mobile = "";
        }

        //去掉手机号字符串的前后空格
        mobile = mobile.trim();

        //把获得的手机号封装在Toeken中
        SmsCodeAuthenticationToken authRequest = new SmsCodeAuthenticationToken(mobile);

        //把请求的信息也设置到Token中，包括IP，SessionId等
        setDetails(request, authRequest);

        //获得AuthenticationManager，遍历AuthenticationProvider(提供校验逻辑的类)，找到support这个authRequest的provider
        return this.getAuthenticationManager().authenticate(authRequest);
    }

    private String obtainUsername(HttpServletRequest request) {
        return request.getParameter(mobileParameter);
    }

    /**
     * 把请求的信息设置到Token中去
     * @param request
     * @param authRequest
     */
    protected void setDetails(HttpServletRequest request, SmsCodeAuthenticationToken authRequest) {
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
    }

    public final String getMobileParameter(){
        return mobileParameter;
    }
}
